﻿using Common.Commands;
using Common.Commands.MemberCommands;
using Core.Domain.Model;
using Core.Infrastructure.CustomExceptions;
using Dto.ApiResponses.MemberResponses;
using Sanelib.Common.Helpers;
using Sanelib.DataOperation;

namespace Core.Processors.MemberProcessors
{
    public class AddMemberProcessor : ICommandProcessor<AddMember>
    {
        private const string UserWithSameUsernameExceptionMssg =
          "A user with the same username already exists in the system.";

        private const string UserWithSameEmailExceptionMssg =
            "A user with the same email address already exists in the system.";

        private readonly IRepository<Member> _memberRepository;

        public AddMemberProcessor(IRepository<Member> memberRepository)
        {
            _memberRepository = memberRepository;
        }

        public dynamic Process(AddMember command)
        {
            EnsureUniqueness(command);

            var member = new Member
            {
                Id = command.Id,
                TagId = command.TagId,
                Code = command.Code,
                Name = command.Name,
                DateOfBirth = command.DateOfBirth,
                Address = command.Address,
                Email = command.Email,
                Mobile = command.Mobile,
                ScreenMessage = command.ScreenMessage,
                ValidFrom = command.ValidFrom,
                ValidTo = command.ValidTo,
                SendSms = command.SendSms,
                SendEmail = command.SendEmail,
                UsePrint = command.UsePrint,
                Block = command.Block,
                Role = command.Role,
                UserStatus = command.UserStatus,                
                FailedAttemptCount = 0,
                ImageData = command.ImageData, 
                CreatedBy  = command.UserId
            };

            _memberRepository.Add(member);
          
            return new MemberResponse
            {
                Id = command.Id,
                Name = command.Name,
                Code = command.Code,
                Description = command.Description,
                ImageData = command.ImageData,                
            };
        }

        private void EnsureUniqueness(AddMember command)
        {
            var userWithSameUsername = _memberRepository.GetByKey(Property.Of<Member>(entity => entity.Name), command.Name);

            if (userWithSameUsername != null)
            {
                throw new DomainProcessException(UserWithSameUsernameExceptionMssg);
            }

            var userWithSameEmail = _memberRepository.GetByKey(Property.Of<Member>(entity => entity.Email),
                                                               command.Email);

            if (userWithSameEmail != null)
            {
                throw new DomainProcessException(UserWithSameEmailExceptionMssg);
            }
        }
    }
}